home *** CD-ROM | disk | FTP | other *** search
/ Over 1,000 Windows 95 Programs / Over 1000 Windows 95 Programs (Microforum) (Disc 1).iso / 1257 / su-dde.c_ / su-dde.c
C/C++ Source or Header  |  1997-04-18  |  28KB  |  768 lines

  1. /* EasyCODE(C++) V5.1 01.03.1995 14:09:58
  2. EasyCODE(C++) sample: DDE communication with Program Manager */
  3. /* EasyCODE O
  4. If=horizontal
  5. LevelNumbers=no
  6. LineNumbers=no
  7. ScreenFont=System,,100,1,-13,0,700,0,0,0,0,0,0,1,2,1,34
  8. PrinterFont=Courier,,100,2,-41,0,400,0,0,0,0,0,0,2,1,2,49
  9. LastLevelId=13 */
  10.  
  11. /* EasyCODE ( 1
  12.    DDE communication with Program Manager */
  13.  
  14. /* EasyCODE ( 13
  15.    Definitions */
  16. /*****************************************************************************/
  17. /*                                                                           */
  18. /*              DDE Communication with Program Manager                       */
  19. /*                                                                           */
  20. /*****************************************************************************/
  21.  
  22. #include <stdlib.h>                                     /* Include-files.    */
  23. #include <string.h>
  24. #include <ctype.h>
  25. #define NOMINMAX                // min(), max() already defined in stdlib.h.
  26. #include <windows.h>
  27. #include <dde.h>
  28. #include "setup.h"
  29.  
  30. void  FAR PASCAL AddProgramToProgMan(HWND);
  31. BOOL  FAR PASCAL ProgManDlgProc(HWND,unsigned,WORD,LONG);
  32. void  FAR PASCAL DoAddIcons(HWND,PSTR,unsigned,BOOL);
  33. BOOL  FAR PASCAL DDESendCommand(HWND, LPSTR *);
  34. void  FAR PASCAL DDEProc(HWND,unsigned,WORD,LONG);
  35. BOOL  FAR PASCAL FillComboBox (HWND, WORD);
  36. void  FAR PASCAL OutOfGlobalHeapSpaceError(HWND);
  37. void  FAR PASCAL OutOfLocalHeapSpaceError(HWND);
  38. void  FAR PASCAL DDEInitiateError(HWND);
  39. void  FAR PASCAL DDEExecuteCommandError(HWND);
  40. void  FAR PASCAL DDEAckTimeOutError(HWND);
  41.  
  42. // --> su-dlg.c
  43. extern void FAR PASCAL CenterPopup(HWND);       // center dialog box!
  44. extern int  _cdecl     DisplayText(HWND,WORD,WORD,WORD,...);
  45. // --> su-lib.c
  46. extern WORD FAR PASCAL GetSetupConfStringSeq(LPSTR,int,LPCSTR,LPSTR,WORD);
  47. extern BOOL FAR PASCAL GetSetupConfBool (LPSTR,BOOL);
  48. extern void FAR PASCAL AddBackslash (LPSTR);
  49. extern BOOL FAR PASCAL SuppressDialog (WORD);
  50.  
  51. // module-specific defines...
  52. #define MAX_PROGRAMS          0xFFFF            /* variable is 'unsigned'. */
  53. #define LEN_PROGMANNAMEBUFFER 256
  54. #define DDE_NO_CONVERSATION   0
  55. #define DDE_INITIATE          1
  56. #define DDE_IDLE              2
  57. #define DDE_WAITINGFORACK     4
  58. #define DDE_TERMINATE         8
  59. #define DDE_TERMINATE_TIMEOUT 3000L             /* milliseconds -  3 sec. */
  60. #define DDE_ACK_TIMEOUT       10000L            /* milliseconds - 10 sec. */
  61.  
  62. // module-specific global variables...
  63. static char  szCommand1Part1[] = "[CreateGroup(";       /* GROUPNAME */
  64. static char  szCommand1Part2[] = ")][ShowGroup(";       /* GROUPNAME */
  65. static char  szCommand1Part3[] = ",1)]";
  66. static char  szCommand2Part1[] = "[ReplaceItem(\"";    /* APPLNAME */
  67. static char  szCommand2Part2[] = "\")]";
  68. static char  szCommand3Part1[] = "[AddItem(";           /* EXEFILENAME */
  69. static char  szCommand3Part2[] = ",\"";         /* APPLNAME */
  70. static char  szCommand3Part3[] = "\",)]";
  71. static int   DDEState = DDE_NO_CONVERSATION;
  72. static HWND  hWndProgMan = (HWND)NULL;
  73. static HANDLE hCommand;
  74. static HANDLE hProgmanData = (HANDLE)NULL;
  75. static PSTR pProgmanData = (PSTR)NULL;
  76. /* EasyCODE ) */
  77.  
  78. /* EasyCODE ( 2
  79.    AddProgramToProgMan */
  80.  
  81. /* EasyCODE F */
  82. //-----------------------------------------------------------------------------
  83. //      Inserting installed programs into ProgMan group
  84. //-----------------------------------------------------------------------------
  85.  
  86. void FAR PASCAL AddProgramToProgMan(HWND hWnd)
  87.    {
  88.    FARPROC  lpprocAddress;
  89.    BOOL     bRetVal, bError = FALSE;
  90.    char     szBuffer[LEN_PROGMANNAMEBUFFER];
  91.    HANDLE   hPrograms = (HANDLE)NULL, oldHandle;
  92.    unsigned nPrograms = 0;
  93.    PSTR     pPrograms;
  94.    MSG      msg;
  95.    DWORD    dwDDETimeOut;
  96.    ATOM     atomAppl, atomTopic;
  97.    
  98.    // ------------------------------------------------------------------------
  99.    // Initiate DDE conversation with program manager.
  100.    atomAppl  = GlobalAddAtom ("PROGMAN");
  101.    atomTopic = GlobalAddAtom ("PROGMAN");
  102.    hWndProgMan = (HWND)NULL;
  103.    DDEState = DDE_INITIATE;
  104.    SendMessage (HWND_BROADCAST, WM_DDE_INITIATE, hWnd, MAKELONG (atomAppl, atomTopic));
  105.    GlobalDeleteAtom (atomAppl);
  106.    GlobalDeleteAtom (atomTopic);
  107.    if (DDEState != DDE_INITIATE || hWndProgMan == (HWND)NULL)
  108.       {
  109.       DDEInitiateError (hWnd);
  110.       return;
  111.       }
  112.    DDEState = DDE_IDLE;                 // Conversation established.
  113.    
  114.    hPrograms = LocalAlloc(LMEM_MOVEABLE,
  115.                           (nPrograms+1)*LEN_PROGMANNAMEBUFFER);
  116.    if ((hPrograms == (HANDLE)NULL) ||            // Error allocating memory.
  117.        ((pPrograms = LocalLock(hPrograms)) == (PSTR)NULL))
  118.       {
  119.       OutOfLocalHeapSpaceError(hWnd);
  120.       goto dde_exit;
  121.       }
  122.    while (nPrograms < MAX_PROGRAMS && !bError)
  123.       {
  124.       *szBuffer = '\0';         // Entries start with 1, nPrograms with 0.
  125.       GetSetupConfStringSeq(infoStrings.lpszKeyProgManEntry, nPrograms + 1, "",
  126.                             (LPSTR)szBuffer, sizeof(szBuffer));
  127.       strcpy(pPrograms + nPrograms*LEN_PROGMANNAMEBUFFER,szBuffer);
  128.       if (*szBuffer == '\0')
  129.          {
  130.          break;
  131.          // No further strings.
  132.          }
  133.       nPrograms++;                              // Next string.
  134.       oldHandle = hPrograms;
  135.       LocalUnlock(hPrograms);
  136.       hPrograms = LocalReAlloc(hPrograms,       // Resize buffer.
  137.                                (nPrograms+1)*LEN_PROGMANNAMEBUFFER,
  138.                                LMEM_MOVEABLE);
  139.       if ((hPrograms == (HANDLE)NULL) ||         // Error allocating memory.
  140.           ((pPrograms = LocalLock(hPrograms)) == (PSTR)NULL))
  141.          {
  142.          LocalFree(oldHandle);
  143.          OutOfLocalHeapSpaceError(hWnd);
  144.          goto dde_exit;
  145.          }
  146.       }
  147.    // Inserting dialog box into ProgMan group.
  148.    lpprocAddress=MakeProcInstance((FARPROC)ProgManDlgProc,hInst);
  149.    bRetVal=DialogBoxParam(hInst,"PROGMANBOX",hWnd,lpprocAddress,
  150.                           MAKELONG(pPrograms,0));
  151.    FreeProcInstance((FARPROC)lpprocAddress);
  152.    if (bRetVal                                   // If desired do it.
  153.       )
  154.       {
  155.       DoAddIcons(hWnd,pPrograms,nPrograms,bReplaceItems);
  156.       }
  157.    LocalUnlock(hPrograms);                      // Free allocated memory.
  158.    LocalFree  (hPrograms);
  159.    
  160.    dde_exit:
  161.       // ------------------------------------------------------------------------
  162.       // Terminate conversation with program manager.
  163.       DDEState = DDE_TERMINATE;
  164.       dwDDETimeOut = GetTickCount() + DDE_TERMINATE_TIMEOUT;
  165.       PostMessage (hWndProgMan, WM_DDE_TERMINATE, hWnd, 0L);
  166.    while (PeekMessage((LPMSG)&msg, (HWND)NULL,
  167.                       WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE))
  168.       {
  169.       // Wait for acknowledge or timeout.
  170.       DispatchMessage((LPMSG)&msg);
  171.       if ((msg.message == WM_DDE_TERMINATE) ||
  172.           (GetTickCount() > dwDDETimeOut))
  173.          {
  174.          break;
  175.          }
  176.       }
  177.    DDEState = DDE_NO_CONVERSATION;
  178.    return;
  179.    }
  180. /* EasyCODE ) */
  181.  
  182. /* EasyCODE ( 3
  183.    ProgManDlgProc */
  184.  
  185. /* EasyCODE F */
  186. //-----------------------------------------------------------------------------
  187. //      Dialog box procedure for inserting programs into ProgMan group
  188. //-----------------------------------------------------------------------------
  189.  
  190. BOOL FAR PASCAL ProgManDlgProc(HWND hDlg,   unsigned message,
  191.                                WORD wParam, LONG     lParam)
  192.    {
  193.    // When inserting icons into a group the name of which exceeds
  194.    // 24 characters by way of DDE, the ProgramManager rewrites an error.
  195.    #define MAX_GROUPNAME_LEN 24
  196.    switch (message)
  197.       {
  198.       static PSTR pPrograms;
  199.              PSTR p;
  200.       WORD        i;
  201.       char        szBuffer[LEN_PROGMANNAMEBUFFER];
  202.       DWORD  dwWinVersion;
  203.       case WM_INITDIALOG:
  204.          if (strlen(szProgmanGroupName) > MAX_GROUPNAME_LEN)
  205.             {
  206.             szProgmanGroupName[MAX_GROUPNAME_LEN] = '\0';
  207.             }
  208.          SetDlgItemText(hDlg,ID_GROUPNAME,(LPSTR)szProgmanGroupName);
  209.          SendDlgItemMessage(hDlg,
  210.                             ID_GROUPNAME,
  211.                             EM_LIMITTEXT,
  212.                             min(sizeof(szProgmanGroupName)-1,
  213.                                 MAX_GROUPNAME_LEN),
  214.                             0L);
  215.          FillComboBox(hDlg, ID_GROUPNAME);
  216.          pPrograms = (PSTR)LOWORD(lParam);
  217.          if (!pPrograms)
  218.             {
  219.             EndDialog(hDlg,FALSE);  // Error.
  220.             }
  221.          p = pPrograms;
  222.          while (*p != '\0')
  223.             {
  224.             strcpy(szBuffer,p);
  225.             *(strchr(szBuffer,':')) = '\0';
  226.             SendDlgItemMessage(hDlg,ID_PROGRAMS,
  227.                                LB_INSERTSTRING,
  228.                                (WPARAM)-1,(LPARAM)(LPSTR)szBuffer);
  229.             p += LEN_PROGMANNAMEBUFFER;
  230.             }
  231.          SendDlgItemMessage(hDlg,ID_PROGRAMS,LB_SETSEL,TRUE,-1L);
  232.          
  233.          // In Windows version < 3.10 hide check box for replacing icons
  234.          dwWinVersion = GetVersion ();
  235.          if (((LOBYTE (LOWORD (dwWinVersion)) << 8) + HIBYTE (LOWORD (dwWinVersion)))
  236.              < 0x030a)
  237.             {
  238.             int yPushButtons, yDist, x[3], y[3];
  239.             RECT rCtlArr[3], rDlg;
  240.             HWND hCtlArr[3];
  241.             
  242.             EnableWindow (GetDlgItem (hDlg, ID_REPLACE_ITEMS), FALSE);
  243.             ShowWindow   (GetDlgItem (hDlg, ID_REPLACE_ITEMS), SW_HIDE);
  244.             yDist = (6 * HIWORD (GetDialogBaseUnits ())) / 8; // y-Distanz fuer Ctls.
  245.             GetWindowRect (GetDlgItem (hDlg, ID_PROGRAMS), (LPRECT)&rCtlArr[0]);
  246.             yPushButtons = rCtlArr[0].bottom + yDist;
  247.             hCtlArr[0] = GetDlgItem (hDlg, ID_TEXT2);
  248.             hCtlArr[1] = GetDlgItem (hDlg, ID_OK);
  249.             hCtlArr[2] = GetDlgItem (hDlg, ID_CANCEL);
  250.             for (i=0; i<3; i++)
  251.                {
  252.                GetWindowRect (hCtlArr[i], (LPRECT)&rCtlArr[i]);
  253.                x[i] = abs (rCtlArr[i].right  - rCtlArr[i].left);
  254.                y[i] = abs (rCtlArr[i].bottom - rCtlArr[i].top);
  255.                rCtlArr[i].top = yPushButtons;
  256.                if (i == 0  // The text must be placed a little lower
  257.                   )
  258.                   {
  259.                   rCtlArr[i].top += 4;
  260.                   }
  261.                rCtlArr[i].bottom = rCtlArr[i].top + y[i];
  262.                ScreenToClient(hDlg, (LPPOINT)&rCtlArr[i]);        // convert left, top.
  263.                MoveWindow(hCtlArr[i],                     // client
  264.                           rCtlArr[i].left, rCtlArr[i].top,
  265.                           x[i], y[i],
  266.                           TRUE);
  267.                }
  268.             // Adjust window size.
  269.             GetWindowRect (hDlg, (LPRECT)&rDlg);
  270.             rDlg.bottom = max (rCtlArr[0].bottom, max (rCtlArr[1].bottom, rCtlArr[2].bottom)) 
  271.                           + yDist
  272.                           + GetSystemMetrics(SM_CYDLGFRAME);
  273.             MoveWindow(hDlg,                     // screen
  274.                        rDlg.left, rDlg.top,
  275.                        abs(rDlg.right-rDlg.left), abs(rDlg.bottom-rDlg.top),
  276.                        TRUE);
  277.             }
  278.          else
  279.             {
  280.             CheckDlgButton (hDlg, ID_REPLACE_ITEMS, bReplaceItems);
  281.             }
  282.          CenterPopup(hDlg);                     // Center!
  283.          if (SuppressDialog (IDS_KEY_SUPPDLGPROGMAN))
  284.             {
  285.             PostMessage (hDlg, WM_COMMAND, ID_YES, 0L);
  286.             }
  287.          else
  288.             {
  289.             SetFocus(GetDlgItem(hDlg,ID_YES));
  290.             }
  291.          return (FALSE);
  292.          break;
  293.       case WM_COMMAND:
  294.          switch (wParam)
  295.             {
  296.             case ID_GROUPNAME:
  297.                // Graying of 'Yes' button.
  298.                if (HIWORD(lParam) == CBN_EDITCHANGE)
  299.                   {
  300.                   EnableWindow(GetDlgItem(hDlg,
  301.                                           ID_YES),
  302.                                SendDlgItemMessage(hDlg,
  303.                                                   ID_GROUPNAME,
  304.                                                   WM_GETTEXTLENGTH,
  305.                                                   0,
  306.                                                   0L) > 0);
  307.                   }
  308.                break;
  309.             case ID_REPLACE_ITEMS:
  310.                bReplaceItems = !IsDlgButtonChecked (hDlg, wParam);
  311.                CheckDlgButton (hDlg, wParam, bReplaceItems);
  312.                break;
  313.             case ID_YES:
  314.                // Inserting the selected programs.
  315.                GetDlgItemText(hDlg,             // Group name.
  316.                               ID_GROUPNAME,
  317.                               (LPSTR)szProgmanGroupName,
  318.                               sizeof(szProgmanGroupName));
  319.                p = pPrograms, i = 0;            // Programs.
  320.                while (*p != '\0')
  321.                   {
  322.                   LONG iRetVal;
  323.                   iRetVal = SendDlgItemMessage(hDlg,ID_PROGRAMS,
  324.                                                LB_GETSEL,i,0L);
  325.                   if ((iRetVal == 0) ||          // Not selected or
  326.                       (iRetVal == LB_ERR)        // error, then delete.
  327.                      )
  328.                      {
  329.                      *p = '\0';
  330.                      }
  331.                   p += LEN_PROGMANNAMEBUFFER, i++;      // Next entry.
  332.                   }
  333.                EndDialog(hDlg,TRUE);
  334.                break;
  335.             case ID_NO:
  336.                // No inserting/closing of programs (control menu).
  337.                EndDialog(hDlg,FALSE);   // cancel dialog box.
  338.                break;
  339.             default:
  340.                return (FALSE);
  341.                break;
  342.             }
  343.          break;
  344.       default:
  345.          break;
  346.       }
  347.    return (FALSE);
  348.    #undef MAX_GROUPNAME_LEN
  349.    }
  350. /* EasyCODE ) */
  351.  
  352. /* EasyCODE ( 4
  353.    DoAddIcons */
  354.  
  355. /* EasyCODE F */
  356. //-----------------------------------------------------------------------------
  357. //      Execution of program insertion into ProgMan group
  358. //-----------------------------------------------------------------------------
  359.  
  360. void FAR PASCAL DoAddIcons(HWND hWnd, PSTR pPrograms, unsigned nPrograms, BOOL bReplaceIcons)
  361.    {
  362.    unsigned i;
  363.    DWORD    dwBytesCommand1, dwBytesCommand2, dwBytesCommand3;
  364.    LPSTR    lpCommand;
  365.    BOOL     bOk = TRUE;
  366.    if (nPrograms == 0 || pPrograms == (PSTR)NULL || *szProgmanGroupName == '\0')
  367.       {
  368.       return;
  369.       }
  370.    // ------------------------------------------------------------------------
  371.    // Construct commands for inserting programs into program manager group.
  372.    dwBytesCommand1 = sizeof (szCommand1Part1)    + 
  373.                      sizeof (szProgmanGroupName) +
  374.                      sizeof (szCommand1Part2)    + 
  375.                      sizeof (szProgmanGroupName) +
  376.                      sizeof (szCommand1Part3);
  377.    if (bReplaceIcons)
  378.       {
  379.       dwBytesCommand2 = sizeof (szCommand2Part1) +
  380.                         LEN_PROGMANNAMEBUFFER   +
  381.                         sizeof (szCommand2Part2);
  382.       }
  383.    else
  384.       {
  385.       dwBytesCommand2 = (DWORD)0;
  386.       }
  387.    dwBytesCommand3 = sizeof (szCommand3Part1) +
  388.                      _MAX_PATH                +
  389.                      sizeof (szCommand3Part2) +
  390.                      LEN_PROGMANNAMEBUFFER   +
  391.                      sizeof (szCommand3Part3);
  392.    
  393.    hCommand = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE,
  394.                            max(dwBytesCommand1, max(dwBytesCommand2, dwBytesCommand3)));
  395.    if ((hCommand == (HANDLE)NULL) ||
  396.        ((lpCommand = GlobalLock(hCommand)) == (LPSTR)NULL))
  397.       {
  398.       OutOfGlobalHeapSpaceError(hWnd);
  399.       bOk = FALSE;
  400.       }
  401.    if (bOk)
  402.       {
  403.       lstrcpy(lpCommand,(LPSTR)szCommand1Part1);
  404.       lstrcat(lpCommand,(LPSTR)szProgmanGroupName);
  405.       lstrcat(lpCommand,(LPSTR)szCommand1Part2);
  406.       lstrcat(lpCommand,(LPSTR)szProgmanGroupName);
  407.       lstrcat(lpCommand,(LPSTR)szCommand1Part3);
  408.       bOk = DDESendCommand (hWnd, &lpCommand);
  409.       }
  410.    if (bOk)
  411.       {
  412.       for (i=0;i<nPrograms;i++             // For all programs.
  413.           )
  414.          {
  415.          PSTR pColon;
  416.          if ((*(pPrograms + i*LEN_PROGMANNAMEBUFFER) != '\0') &&
  417.              (pColon = strchr(pPrograms+i*LEN_PROGMANNAMEBUFFER,':')))
  418.             {
  419.             LPSTR p1, p2;
  420.             
  421.             *pColon = '\0';         // Separate string at ':'.
  422.             p1 = (LPSTR)(pPrograms + i*LEN_PROGMANNAMEBUFFER); // Before ':'.
  423.             p2 = (LPSTR)(pColon + 1);                          // After  ':'.
  424.             AnsiUpper(p2);  // szDestPath is already uppercase.
  425.             if (bReplaceIcons)
  426.                {
  427.                lstrcpy(lpCommand,(LPSTR)szCommand2Part1); // "[ReplaceItem(\""
  428.                lstrcat(lpCommand,(LPSTR)p1);              // Application name
  429.                lstrcat(lpCommand,(LPSTR)szCommand2Part2); // "\")]
  430.                DDESendCommand (hWnd, &lpCommand);
  431.                }
  432.             lstrcpy(lpCommand,(LPSTR)szCommand3Part1); // "[AddItem("
  433.             if (!_fstrpbrk((LPSTR)p2, (LPSTR)"\\/:"))
  434.                {
  435.                lstrcat(lpCommand,(LPSTR)szDestPath); // Full pathname if no path specified
  436.                AddBackslash (lpCommand);             // in SETUP.INF
  437.                }
  438.             lstrcat(lpCommand,(LPSTR)p2);           // EXE filename.
  439.             lstrcat(lpCommand,(LPSTR)szCommand3Part2);
  440.             lstrcat(lpCommand,(LPSTR)p1);           // Application name.
  441.             lstrcat(lpCommand,(LPSTR)szCommand3Part3);
  442.             DDESendCommand (hWnd, &lpCommand);
  443.                     // if (*pPrograms ... )
  444.             }
  445.          // for ( ... )
  446.          }
  447.       // if (!bError)
  448.       }
  449.    BringWindowToTop(hWnd);       // Make setup window top window again!
  450.    if (hCommand)
  451.       {
  452.       GlobalUnlock (hCommand);
  453.       GlobalFree (hCommand);
  454.       }
  455.    return;
  456.    }
  457. /* EasyCODE ) */
  458.  
  459. /* EasyCODE ( 5
  460.    DDESendCommand */
  461.  
  462. /* EasyCODE F */
  463. //---------------------------------------------------------------------------
  464. //                      DDESendCommand ()
  465. //---------------------------------------------------------------------------
  466. // Sends a DDE command to the Program Manager.
  467. // In:  hWnd      ... Window handle
  468. // Out: lpCommand ... pointer to command buffer pointer which will be assigned 
  469. //                    again because of "GlobalUnlock()" at the beginning of the 
  470. //                    function and "GlobalLock()" at the end!
  471. // Return: TRUE -> no error occurred.
  472. //---------------------------------------------------------------------------
  473.  
  474. BOOL FAR PASCAL DDESendCommand (HWND hWnd, LPSTR *lpCommand)
  475.    {
  476.    MSG   msg;
  477.    DWORD dwDDETimeOut;
  478.    BOOL bOk = TRUE;
  479.     
  480.    GlobalUnlock (hCommand);              // Unlock command.
  481.    
  482.    // ------------------------------------------------------------------------
  483.    // Send command to program manager for execution.
  484.    if (!PostMessage(hWndProgMan,  // Post execute command message.
  485.                     WM_DDE_EXECUTE,
  486.                     hWnd,
  487.                     MAKELONG(0,hCommand)))
  488.       {
  489.       bOk = FALSE;
  490.       }
  491.    // ------------------------------------------------------------------------
  492.    // Wait for acknowledge for command.
  493.    if (bOk)
  494.       {
  495.       DDEState = DDE_WAITINGFORACK;
  496.       dwDDETimeOut = GetTickCount() + DDE_ACK_TIMEOUT;
  497.       while ((DDEState == DDE_WAITINGFORACK) &&
  498.              (GetTickCount() < dwDDETimeOut))
  499.          {
  500.          // Wait until DDE_ACK or timeout.
  501.          if (PeekMessage ((LPMSG)&msg, (HWND)NULL, 0, WM_USER, PM_REMOVE))
  502.             {
  503.             TranslateMessage ((LPMSG)&msg);
  504.             DispatchMessage ((LPMSG)&msg);
  505.             }
  506.          }
  507.       if (DDEState == DDE_WAITINGFORACK   // Timeout.
  508.          )
  509.          {
  510.          DDEAckTimeOutError(hWnd);
  511.          DDEState = DDE_IDLE;
  512.          bOk = FALSE;
  513.          }
  514.       }
  515.    *lpCommand = GlobalLock (hCommand);
  516.    return (bOk);
  517.    }
  518. /* EasyCODE ) */
  519.  
  520. /* EasyCODE ( 6
  521.    DDEProc */
  522.  
  523. /* EasyCODE F */
  524. //-----------------------------------------------------------------------------
  525. //      Handling of incoming DDE messages
  526. //-----------------------------------------------------------------------------
  527.  
  528. void FAR PASCAL DDEProc(HWND hWnd, unsigned msg, WORD wParam, LONG lParam)
  529.    {
  530.    DDEACK   ddeAck;
  531.    WORD     wDummy1, wDummy2, wDataLen;
  532.    LPSTR    lpStr;
  533.    BOOL     bRelease;
  534.    DDEDATA  FAR *lpDDEData;
  535.    HGLOBAL  hData;
  536.    ATOM     atomItem;
  537.    switch (msg)
  538.       {
  539.       case WM_DDE_ACK:
  540.          // Request accepted.
  541.          switch (DDEState)
  542.             {
  543.             case DDE_INITIATE:
  544.                // Conversation accepted?
  545.                GlobalDeleteAtom ((ATOM)LOWORD(lParam));
  546.                GlobalDeleteAtom ((ATOM)HIWORD(lParam));
  547.                if (hWndProgMan == (HWND)NULL         // No conversation until yet.
  548.                   )
  549.                   {
  550.                   hWndProgMan = wParam;               // Window handle of ProgMan.
  551.                   }
  552.                break;
  553.             case DDE_WAITINGFORACK:
  554.                // Command accepted?
  555.                wDummy1 = LOWORD (lParam);
  556.                wDummy2 = HIWORD (lParam);
  557.                if (wDummy2 && wDummy2 != hCommand)
  558.                   {
  559.                   hCommand = (HANDLE)wDummy2; // Server has created a new memory handle
  560.                   }
  561.                ddeAck = *((DDEACK *)&wDummy1);
  562.                if (ddeAck.fAck               // Command executed.
  563.                   )
  564.                   {
  565.                   DDEState = DDE_IDLE;
  566.                   }
  567.                else
  568.                   {
  569.                   // Error executing command.
  570.                   /* EasyCODE - */
  571.                   lpStr = GlobalLock ((HANDLE)wDummy2);
  572.                   if (!_fstrstr (lpStr, szCommand2Part1)   // If "ReplaceItem()" fails,
  573.                      )
  574.                      {
  575.                      DDEExecuteCommandError (hWnd);         // no error message output
  576.                      }
  577.                   GlobalUnlock ((HANDLE)wDummy2);
  578.                   DDEState = DDE_IDLE;
  579.                   }
  580.                break;
  581.             default:
  582.                break;
  583.             }
  584.          break;
  585.       case WM_DDE_DATA:
  586.          hData = LOWORD (lParam);
  587.          atomItem = HIWORD (lParam);
  588.          if (!(lpDDEData = (DDEDATA FAR*)GlobalLock (hData)) ||
  589.              (lpDDEData->cfFormat != CF_TEXT))
  590.             {
  591.             // Send negative acknowledge to server.
  592.             PostMessage (hWndProgMan, WM_DDE_ACK, hWnd, MAKELONG (0, atomItem));
  593.             pProgmanData = NULL;
  594.             }
  595.          else
  596.             {
  597.             wDataLen = lstrlen (lpDDEData->Value);
  598.             if ((hProgmanData = LocalAlloc (LMEM_MOVEABLE, wDataLen+1)) == NULL ||
  599.                 (pProgmanData = LocalLock (hProgmanData)) == NULL)
  600.                {
  601.                OutOfGlobalHeapSpaceError(hWnd);
  602.                }
  603.             // Copy DDE data.
  604.             lstrcpy ((LPSTR)pProgmanData, lpDDEData->Value);
  605.             LocalUnlock (hProgmanData);
  606.             if (lpDDEData->fAckReq)
  607.                {
  608.                PostMessage (hWndProgMan, WM_DDE_ACK, hWnd, 
  609.                             MAKELONG (0x8000, atomItem));
  610.                }
  611.             bRelease = lpDDEData->fRelease;
  612.             GlobalUnlock (hData);
  613.             if (bRelease)
  614.                {
  615.                GlobalFree (hData);
  616.                }
  617.             }
  618.          DDEState = DDE_IDLE;
  619.          break;
  620.       case WM_DDE_TERMINATE:
  621.          if (wParam == hWndProgMan)
  622.             {
  623.             if (DDEState != DDE_TERMINATE)
  624.                {
  625.                PostMessage (hWndProgMan, WM_DDE_TERMINATE, hWnd, 0L);
  626.                }
  627.             DDEState = DDE_NO_CONVERSATION;
  628.             }
  629.          break;
  630.       default:
  631.          break;
  632.       }
  633.    }
  634. /* EasyCODE ) */
  635.  
  636. /* EasyCODE ( 7
  637.    FillComboBox */
  638.  
  639. /* EasyCODE F */
  640. //---------------------------------------------------------------------------
  641. //                      FillComboBox ()
  642. //---------------------------------------------------------------------------
  643. // The function determines the names of the existing program groups by
  644. // way of DDE request. These names will then be inserted into the
  645. // list box "idControl" of the dialog box "hDlg".
  646. //---------------------------------------------------------------------------
  647. // Input:  hDlg      ... dialog box handle
  648. //         idControl ... Id of the combobox
  649. // Return: TRUE -> successful insertion; FALSE -> error occurred
  650. //---------------------------------------------------------------------------
  651.  
  652. BOOL FAR PASCAL FillComboBox (HWND hDlg, WORD idControl)
  653.    {
  654.    BOOL bOk = TRUE;
  655.    ATOM atomAppl;
  656.    DWORD dwDDETimeOut;
  657.    MSG   msg;
  658.    PSTR pGroup;
  659.    
  660.    atomAppl = GlobalAddAtom ("PROGMAN");
  661.    if (!PostMessage(hWndProgMan,  // Post request command message.
  662.                     WM_DDE_REQUEST,
  663.                     hWindow,
  664.                     MAKELONG(CF_TEXT, atomAppl)))
  665.       {
  666.       GlobalDeleteAtom (atomAppl);
  667.       bOk = FALSE;
  668.       }
  669.    // ------------------------------------------------------------------------
  670.    // Wait for acknowledge for command.
  671.    if (bOk)
  672.       {
  673.       DDEState = DDE_WAITINGFORACK;
  674.       dwDDETimeOut = GetTickCount() + DDE_ACK_TIMEOUT;
  675.       while ((DDEState == DDE_WAITINGFORACK) &&
  676.              (GetTickCount() < dwDDETimeOut))
  677.          {
  678.          // Wait until DDE_ACK or timeout.
  679.          if (PeekMessage ((LPMSG)&msg, (HWND)NULL, 0, WM_USER, PM_REMOVE))
  680.             {
  681.             TranslateMessage ((LPMSG)&msg);
  682.             DispatchMessage ((LPMSG)&msg);
  683.             }
  684.          }
  685.       if (DDEState == DDE_WAITINGFORACK   // Timeout.
  686.          )
  687.          {
  688.          DDEAckTimeOutError(hWindow);
  689.          DDEState = DDE_IDLE;
  690.          bOk = FALSE;
  691.          }
  692.       }
  693.    if (bOk && (pProgmanData =(PSTR)LocalLock (hProgmanData)) != NULL)
  694.       {
  695.       pGroup = strtok (pProgmanData, "\r\n");
  696.       while (pGroup)
  697.          {
  698.          if (strlen (pGroup))
  699.             {
  700.             SendDlgItemMessage (hDlg, idControl, CB_ADDSTRING, 0, (LPARAM)(LPSTR)pGroup);
  701.             }
  702.          pGroup = strtok (NULL, "\r\n");
  703.          }
  704.       }
  705.    if (hProgmanData)
  706.       {
  707.       LocalUnlock (hProgmanData);
  708.       hProgmanData = LocalFree (hProgmanData);
  709.       }
  710.    return bOk;
  711.    }
  712. /* EasyCODE ) */
  713.  
  714. /* EasyCODE ( 8
  715.    OutOfGlobalHeapSpaceError */
  716.  
  717. /* EasyCODE F */
  718. //-----------------------------------------------------------------------------
  719. //      Various error messages
  720. //-----------------------------------------------------------------------------
  721.  
  722. void  FAR PASCAL OutOfGlobalHeapSpaceError(HWND hWnd)
  723.    {
  724.    DisplayText(hWnd, IDS_OUTOFGLOBALHEAPSPACE, 0, MB_ICONEXCLAMATION);
  725.    }
  726. /* EasyCODE ) */
  727.  
  728. /* EasyCODE ( 9
  729.    OutOfLocalHeapSpaceError */
  730.  
  731. /* EasyCODE F */
  732. void  FAR PASCAL OutOfLocalHeapSpaceError(HWND hWnd)
  733.    {
  734.    DisplayText(hWnd, IDS_OUTOFLOCALHEAPSPACE, 0, MB_ICONEXCLAMATION);
  735.    }
  736. /* EasyCODE ) */
  737.  
  738. /* EasyCODE ( 10
  739.    DDEInitiateError */
  740.  
  741. /* EasyCODE F */
  742. void  FAR PASCAL DDEInitiateError(HWND hWnd)
  743.    {
  744.    DisplayText(hWnd, IDS_INITIATEERROR, 0, MB_ICONEXCLAMATION);
  745.    }
  746. /* EasyCODE ) */
  747.  
  748. /* EasyCODE ( 11
  749.    DDEExecuteCommandError */
  750.  
  751. /* EasyCODE F */
  752. void  FAR PASCAL DDEExecuteCommandError(HWND hWnd)
  753.    {
  754.    DisplayText(hWnd, IDS_DDEEEXECERROR, 0, MB_ICONEXCLAMATION);
  755.    }
  756. /* EasyCODE ) */
  757.  
  758. /* EasyCODE ( 12
  759.    DDEAckTimeOutError */
  760.  
  761. /* EasyCODE F */
  762. void  FAR PASCAL DDEAckTimeOutError(HWND hWnd)
  763.    {
  764.    DisplayText(hWnd, IDS_DDEACKTIMEOUT, 0, MB_ICONEXCLAMATION);
  765.    }
  766. /* EasyCODE ) */
  767. /* EasyCODE ) */
  768.